package com.zhdl.hardware.modules.web.service.impl;

import cn.hutool.json.JSONUtil;
import com.google.common.primitives.Bytes;
import com.project.common.util.ByteHelper;
import com.zhdl.hardware.io.smartLink.repository.IOCmdHandleDao;
import com.zhdl.hardware.modules.service.impl.DeviceServiceImpl;
import com.zhdl.hardware.modules.web.request.HCMotorReq;
import com.zhdl.hardware.modules.web.request.SmartLinkIOReq;
import com.zhdl.hardware.modules.web.response.DeviceInfoResp;
import com.zhdl.hardware.modules.web.service.HardwareDebugService;
import com.zhdl.hardware.motor.huichuan.repository.HcPortCmdHandleDao;
import com.zhdl.websocket.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@Slf4j
@Service
public class HardwareDebugServiceImpl implements HardwareDebugService {


    @Resource
    public ThreadPoolTaskScheduler taskScheduler1;
    @Resource
    public WebSocketService webSocketService;
    @Resource
    public IOCmdHandleDao ioCmdHandleDao;
    @Resource
    public HcPortCmdHandleDao hcCmdHandleDao;
    HCMotorReq motorReq = new HCMotorReq();
    SmartLinkIOReq smartLinkIOReq = new SmartLinkIOReq();
    Map<String, Object> maps = new ConcurrentHashMap<>();
    Map<String, ScheduledFuture> mapSF = new ConcurrentHashMap<>();
    @Resource
    private DeviceServiceImpl deviceService;

    /**
     * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
     */
    public static Byte[] getBitArray(byte b) {
        Byte[] array = new Byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte) (b & 1);
            b = (byte) (b >> 1);
        }
        return array;
    }

    /**
     * List<Byte> to str
     *
     * @param bytes 字节数组
     * @return /
     */
    public String byteArrayToStr(List<Byte> bytes) {

        byte[] array = Bytes.toArray(bytes);
        StringBuffer stringBuffer = new StringBuffer();

        for (byte b : array) {
            stringBuffer.append(b);
        }

        return stringBuffer.toString();
    }

    /**
     * HardwareDebug-
     * 开启IO信号读取-
     * 以及电机当前位置读取
     */
    @Override
    public void hardwareReadStart() {

        List<DeviceInfoResp> allDevice = deviceService.findAllDevice();

        for (DeviceInfoResp deviceInfoResp : allDevice) {
            if (deviceInfoResp.getTypeId() == 0) {
                Integer mId = deviceInfoResp.getDeviceProcess().getMId();
                String port = deviceInfoResp.getDeviceProcess().getPort();
                String slaveId = deviceInfoResp.getDeviceProcess().getSlaveId();
                ScheduledFuture<?> scheduledFuture = taskScheduler1.scheduleWithFixedDelay(() ->
                        hcCmdHandleDao.motorReadSlagLocation(port, slaveId, "0B07", bytes -> {
                            byte[] mPosition;
                            mPosition = new byte[4];

                            mPosition[2] = bytes[0];
                            mPosition[3] = bytes[1];
                            mPosition[0] = bytes[2];
                            mPosition[1] = bytes[3];

                            String s = ByteHelper.bytesArrayToHexString(mPosition);
                            BigInteger bigInteger = new BigInteger(s, 16);
                            int motorCurrentLocation = bigInteger.intValue();
                            motorReq.setLocation(String.valueOf(motorCurrentLocation));
                            maps.put(mId.toString(), motorReq);
                            String jsonStr = JSONUtil.toJsonStr(maps);
                            webSocketService.sendMessage(jsonStr);
                        }), 1000);
                mapSF.put("motor-" + mId, scheduledFuture);
            }
        }

        for (DeviceInfoResp deviceInfoResp : allDevice) {
            if (deviceInfoResp.getTypeId() == 1) {
                Integer mId = deviceInfoResp.getDeviceProcess().getMId();
                ScheduledFuture<?> scheduledFuture = taskScheduler1.scheduleWithFixedDelay(() -> {
                    ioCmdHandleDao.ioReadDiscreteSignal("10", bytes -> {
                        /* 获取当前指令返回的数据 */
                        /* 对返回的数据进行处理 - 每八位进行高低位反转 */
                        List<Byte> ioList = new ArrayList<>();
                        for (byte b : bytes) {
                            Byte[] bitArray = getBitArray(b);
                            ioList.addAll(Arrays.asList(bitArray));
                        }
                        String io02 = byteArrayToStr(ioList);
                        smartLinkIOReq.setIo02(io02);
                        maps.put(String.valueOf(mId), smartLinkIOReq);
                        String jsonStr = JSONUtil.toJsonStr(maps);
                        webSocketService.sendMessage(jsonStr);
                        log.info("IO信号为:" + jsonStr);
                    });
                }, 100);
                mapSF.put("io-" + mId, scheduledFuture);
            }
        }
    }

    /**
     * HardwareDebug-
     * 取消IO信号读取-
     * 以及电机当前位置读取
     */
    @Override
    public void hardwareReadEnd() {
        for (String s : mapSF.keySet()) {
            ScheduledFuture scheduledFuture = mapSF.get(s);
            scheduledFuture.cancel(true);
            mapSF.remove(s);
        }
    }

}
